package com.okilo.online.app.act

import android.annotation.SuppressLint
import android.os.CountDownTimer
import android.view.View
import androidx.recyclerview.widget.DefaultItemAnimator
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import com.okilo.online.app.R
import com.okilo.online.app.common.OkiloComAct
import com.okilo.online.app.databinding.OkiloActOnlineChatBinding
import com.okilo.online.app.event.OkiloEventData
import com.okilo.online.app.event.OkiloEventPointType
import com.okilo.online.app.tools.OkiloDensityUtil
import com.okilo.online.app.tools.apt.OkiloOnSingleClickListener
import com.okilo.online.app.tools.decoration.LinearSpacingItemDecoration
import com.okilo.online.app.tools.shared.OkiloSharedHp
import com.okilo.online.app.tools.shared.OkiloSharedKey
import com.okilo.online.app.apt.OkiloOnlineChatApt
import com.okilo.online.app.pet.OkiloChatPet
import com.okilo.online.app.pet.view.IOkiloChat
import com.okilo.online.app.weight.font.OkiloRbtMediumEditText
import org.json.JSONObject

/**
 * 在线客服
 */
class OkiloOnlineChatAct: OkiloComAct(), IOkiloChat {
    lateinit var binding: OkiloActOnlineChatBinding
    private var presenter: OkiloChatPet? = null
    private var chatPage = 1

    //等待时长
    private var countdownTimer: OkiloOnlineChatRefreshCountDownTimer? = null
    private var countdown = 10

    private var chatAdapter: OkiloOnlineChatApt? = null

    override val pageName: String = "UserChat_Page"

    override fun createOkiloContentView(): View {
        binding = OkiloActOnlineChatBinding.inflate(layoutInflater)
        return binding.root
    }

    override fun initializeOkiloViews() {
        getTitleBarManager()
            .setTitleBarVisibility(View.VISIBLE)
            .setTitle(getString(R.string.okilo_service_customer_feedback))
            .setTitleColor(getColor(R.color.okilo_color_black))
            .setBackButtonIcon(R.mipmap.okilo_root_back_icon)
            .setRightButtonVisibility(View.GONE)
            .setTitleBarColor(getColor(R.color.okilo_color_white))
            .setRootBackgroundColor(getColor(R.color.okilo_color_ffeff1f3))

        binding.okiloOnlineChatRefreshView.setColorSchemeResources(R.color.okilo_color_theme, R.color.okilo_color_ff6200ee)
        initOkiloOnlineChatListView()
    }

    @SuppressLint("ClickableViewAccessibility")
    override fun setupOkiloEventListeners() {
        //内容输入框
        binding.okiloOnlineChatEdit.setInputFocusChangeListener(object : OkiloRbtMediumEditText.IInputFocusChangeListener {
            override fun onFocusChange(v: View?, hasFocus: Boolean) {
                if (hasFocus){
                    sOkiloOnlineChatListScrollToLastItem()
                }
            }
            override fun onCompleteAction(v: View?, remark: String?) {
            }
        })
        //发送
        binding.okiloOnlineChatButtonSend.setOnClickListener(object : OkiloOnSingleClickListener(){
            override fun onSingleClick(v: View?) {
                val text = gOkiloOnlineChatText()
                if (text.isEmpty()){
                    return
                }
                addEventPointRequestAction(OkiloEventPointType.OKILO_CLICK_TRACK.USER_CUSTOMER_CHAT_SEND,text)
                presenter?.sendOkiloCustomerOnlineChatMsgAction(text)
            }
        })
        binding.okiloOnlineChatRefreshView.setOnClickListener {
            onHideSoftInput()
            binding.okiloOnlineChatEdit.clearFocus()
        }
        //加载
        binding.okiloOnlineChatRefreshView.setOnRefreshListener {
            chatPage++
            presenter?.gOkiloCustomerOnlineChatRecordAction(chatPage)
        }
    }

    override fun loadOkiloData() {
        if (presenter == null){
            presenter = OkiloChatPet(this)
        }
        showOkiloLoading()
        presenter?.gOkiloCustomerOnlineChatRecordAction(chatPage)
    }

    /**
     * 初始化权限列表
     */
    private fun initOkiloOnlineChatListView(){
        setupRecyclerViewBasics()
        setupChatAdapterAndListeners()
    }

    private fun setupRecyclerViewBasics() {
        with(binding.okiloOnlineChatListView) {
            isNestedScrollingEnabled = false
            layoutManager = createVerticalLinearLayoutManager()
            itemAnimator = DefaultItemAnimator()
            addVerticalSpacingDecoration(16f)
        }
    }

    private fun setupChatAdapterAndListeners() {
        chatAdapter = OkiloOnlineChatApt(binding.okiloOnlineChatListView).apply {
            setChatGuessItemClickListener(createChatGuessClickListener())
        }
        binding.okiloOnlineChatListView.adapter = chatAdapter
    }

    private fun createVerticalLinearLayoutManager() =
        LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false)

    private fun RecyclerView.addVerticalSpacingDecoration(dp: Float) {
        val spacing = OkiloDensityUtil.dp2px(dp)
        addItemDecoration(LinearSpacingItemDecoration(0, 0, spacing, spacing))
    }

    private fun createChatGuessClickListener() =
        object : OkiloOnlineChatApt.IChatGuessClickListener {
            override fun onGuessItemClick(text: String) {
                trackChatSendEvent(text)
                sendChatMessage(text)
            }
        }

    private fun trackChatSendEvent(text: String) {
        addEventPointRequestAction(OkiloEventPointType.OKILO_CLICK_TRACK.USER_CUSTOMER_CHAT_SEND, text)
    }

    private fun sendChatMessage(text: String) {
        presenter?.sendOkiloCustomerOnlineChatMsgAction(text)
    }

    /**
     * 设置会话记录列表
     */
    override fun sOkiloOnlineChatRecordList(recordList: ArrayList<JSONObject>) {
        //第一页
        if (chatPage == 1){
            chatAdapter?.data = recordList
            onOkiloOnlineChatFormatLocalChat()
            sOkiloOnlineChatListScrollToLastItem()
            return
        }
        //没有更多数据
        if (recordList.size == 0){
            chatPage -= 1
        }

        //排除相同会话信息
        val idSet = HashSet<String>()
        chatAdapter?.let {
            for (item in it.data){
                val id = item.optString("id")
                if (!idSet.contains(id)){
                    idSet.add(id)
                }
            }

            val oldList = arrayListOf<JSONObject>()
            for (item in recordList){
                val id = item.optString("id")
                if (!idSet.contains(id)){
                    oldList.add(item)
                }
            }
            it.addNewData(oldList)
        }
    }

    /**
     * 定时5秒更新会话信息列表
     */
    @SuppressLint("NotifyDataSetChanged")
    override fun sOkiloOnlineChatUpdaeRecordList(recordList: ArrayList<JSONObject>) {
        //排除相同会话信息
        val idSet = HashSet<String>()
        chatAdapter?.let {
            for (item in it.data){
                val id = item.optString("id")
                if (!idSet.contains(id)){
                    idSet.add(id)
                }
            }

            val newList = arrayListOf<JSONObject>()
            for (item in recordList){
                val id = item.optString("id")
                if (!idSet.contains(id)){
                    newList.add(item)
                }
            }
            if (newList.isNotEmpty()){
                it.addMoreData(newList)
                sOkiloOnlineChatListScrollToLastItem()

                //获取列表最后一条消息
                val lastItem = it.lastItem
                lastItem?.let {  item ->
                    //最后一条信息不是发送类型，需要停在倒计时，并刷新列表
                    if (item.optString("itemType") != "itemSend"){
                        if (countdownTimer != null){
                            countdownTimer?.cancel()
                            countdownTimer = null
                        }
                        it.notifyDataSetChanged()
                    }
                }
            }
        }
    }

    /**
     * 手动添加本地信息规则
     * 添加欢迎提示语： 会话记录为空 || 最后一条消息时间已超过5分钟
     * Guess ： 会话记录为空 || 最后一条消息时间已超过10分钟
     */
    private fun onOkiloOnlineChatFormatLocalChat(){
        val chatLength = chatAdapter?.itemCount
        if (chatLength == 0){
            //手动添加一条欢迎信息
            insertOkiloOnlineChatLocalWelcomeItem()
            //手动添加一条Guess信息
            insertOkiloOnlineChatLocalGuessItem()
            return
        }
        //上一次会话时间戳
        val chatLastTime = OkiloSharedHp.gOkiloSharedString(OkiloSharedKey.SP_OKILO_CHAT_LAST_TIME)
        if (chatLastTime.isEmpty()){//重新登录 || 换设备登录  没有上一次会话时间记录  需要默认添加
            //手动添加一条欢迎信息
            insertOkiloOnlineChatLocalWelcomeItem()
            //手动添加一条Guess信息
            insertOkiloOnlineChatLocalGuessItem()
            return
        }

        //上次会话时间 > 5分钟
        if (System.currentTimeMillis() - chatLastTime.toLong() > 5 * 60 * 1000){
            //手动添加一条欢迎信息
            insertOkiloOnlineChatLocalWelcomeItem()
        }

        //上次会话时间 > 10分钟
        if (System.currentTimeMillis() - chatLastTime.toLong() > 10 * 60 * 1000){
            //手动添加一条Guess信息
            insertOkiloOnlineChatLocalGuessItem()
        }
    }

    /**
     * 添加一条欢迎提示本地信息
     */
    private fun insertOkiloOnlineChatLocalWelcomeItem(){
        val item = JSONObject()
        item.put("id",System.currentTimeMillis())
        item.put("itemType","itemReceived")
        item.put("talkInfo",getString(R.string.okilo_online_chat_reminder))
        item.put("createTimeStamp",System.currentTimeMillis())
        insertOkiloOnlineChatNewChat(item)
    }

    /**
     * 添加一条Guess本地信息
     */
    private fun insertOkiloOnlineChatLocalGuessItem(){
        val item = JSONObject()
        item.put("id",System.currentTimeMillis())
        item.put("itemType","itemGuess")
        item.put("talkInfo",getString(R.string.okilo_online_chat_guess))
        item.put("createTimeStamp",System.currentTimeMillis())
        insertOkiloOnlineChatNewChat(item)
    }

    /**
     * 添加一条新消息
     */
    override fun insertOkiloOnlineChatNewChat(item: JSONObject) {
        //插入新消息前，最后一条消息类型为 “itemGuess”，需要移除后再添加最新信息
        val lastItem = chatAdapter?.lastItem
        lastItem?.let {
            if (it.optString("itemType") == "itemGuess"){
                chatAdapter?.removeItem(it)
            }
        }
        chatAdapter?.addLastItem(item)
        sOkiloOnlineChatListScrollToLastItem()
    }

    /**
     * 会话列表滑动到最底部
     */
    private fun sOkiloOnlineChatListScrollToLastItem(){
        chatAdapter?.let {
            binding.okiloOnlineChatListView.post {
                binding.okiloOnlineChatListView.scrollToPosition(it.itemCount - 1)
            }
        }
    }

    /**
     * 发送消息成功
     */
    @SuppressLint("NotifyDataSetChanged")
    override fun sOkiloOnlineChatSendSuccess() {
        binding.okiloOnlineChatEdit.setText("")
        chatAdapter?.notifyDataSetChanged()
        //获取列表最后一条消息
        val lastItem = chatAdapter?.lastItem
        lastItem?.let {  item ->
            if (item.optString("itemType") == "itemSend"){
                val createTimeStamp = item.optString("createTimeStamp","0")
                val intervalTime = (System.currentTimeMillis() - createTimeStamp.toLong()) / 1000
                if (intervalTime <= 10){
                    countdown = (10 - intervalTime).toInt()
                    startOkiloOnlineChatCountdownTimer()
                }
            }
        }
    }

    /**
     * 获取发送的内容
     */
    private fun gOkiloOnlineChatText(): String{
        return binding.okiloOnlineChatEdit.text.toString().trim()
    }

    /**
     * 更新最后一条发送的消息状态
     */
    private fun notifyLastItemState(){
        //获取列表最后一条消息
        chatAdapter?.let { adapter ->
            val lastItem = adapter.lastItem
            lastItem?.let {  item ->
                if (item.optString("itemType") == "itemSend"){
                    adapter.notifyItemChanged(adapter.itemCount - 1,"update-state")
                }
            }
        }
    }

    /**
     * 最后一条发送的信息 发送时间超过10秒
     */
    private fun notifyLastItemStateFinish(){
        notifyLastItemState()
        sOkiloOnlineChatListScrollToLastItem()
    }

    /**
     * 启动倒计时
     */
    private fun startOkiloOnlineChatCountdownTimer() {
        if (countdownTimer != null){
            countdownTimer?.cancel()
            countdownTimer = null
        }
        //随机 10秒 等待时长
        countdownTimer = OkiloOnlineChatRefreshCountDownTimer(this, countdown * 1000, 1000)
        countdownTimer?.start()
    }

    class OkiloOnlineChatRefreshCountDownTimer(private val act: OkiloOnlineChatAct, millisInFuture: Int, countDownInterval: Long): CountDownTimer(millisInFuture.toLong(), countDownInterval) {
        override fun onTick(millisUntilFinished: Long) {
            // 这里每隔一段时间（定时器间隔）会被调用
            // 可以在这里更新UI，显示剩余时间
            act.countdown = (millisUntilFinished / 1000).toInt()
            act.notifyLastItemState()
        }
        override fun onFinish() {
            // 倒计时完成时被调用
            act.notifyLastItemStateFinish()
        }
    }

    override fun onOkiloPublishEvent(event: OkiloEventData) {
        super.onOkiloPublishEvent(event)
        when(event.eventType){
            OkiloEventData.TYPE.OKILO_HTTP_REQUEST_ERROR -> {
                hideOkiloLoading()
            }
            else -> {

            }
        }
    }

    override fun hideOkiloLoading() {
        super.hideOkiloLoading()
        binding.okiloOnlineChatRefreshView.isRefreshing = false
    }

    override fun onDestroy() {
        super.onDestroy()
        //记录上次会话时间戳
        OkiloSharedHp.sOkiloSharedData(OkiloSharedKey.SP_OKILO_CHAT_LAST_TIME,"${System.currentTimeMillis()}")
        presenter?.onDestroy()
        if (countdownTimer != null){
            countdownTimer?.cancel()
            countdownTimer = null
        }
    }
}